// 所以实质上创建代理对象时指定的拦截函数，是用来自定义代理对象本身的内部方法和行为的，
// 而不是指定被代理对象的内部方法和行为的。

const fn = (name) => {
  console.log("fn", name);
};
/**
 * 拦截函数
 * apply方法拦截函数调用、call和apply操作
 * apply方法可接受三个参数，分别是
 * 目标对象，目标对象的上下文对象（this），目标对象的参数数组。
 */
let p2 = new Proxy(fn, {
  //apply 拦截函数调用
  apply(target, thisArg, args) {
    return target.call(thisArg, ...args);
  },
});
// p2("张三");

/**
[[GetPrototypeOf]]	getPrototypeOf
[[SetPrototypeOf]]	setPrototypeOf
[[IsExtensible]]	isExtensible
[[PreventExtensions]]	preventExtensions
[[GetOwnProperty]]	getOwnPropertyDescriptor
[[DefineOwnProperty]]	defineProperty
[[HasProperty]]	has
[[Get]]	get
[[Set]]	set
[[Delete]]	deleteProperty
[[OwnPropertyKeys]]	ownKeys
[[Call]]	apply
[[Construct]]	construct
 */
const obj = {
  name: "张三",
};

let p4 = new Proxy(obj, {
  // 拦截对象的读取操作 p4.name
  get(target, key) {
    console.log("get", target, key);
    return Reflect.get(target, key);
  },
  //ownKeys 拦截对象自身属性的读取 for in
  ownKeys(target) {
    console.log("ownKeys", target);
    return Reflect.ownKeys(target);
  },
  // 拦截对象的in操作符
  has(target, key) {
    console.log("has", target, key);
    return Reflect.has(target, key);
  },
  // 拦截对象的删除操作 delete p4.name
  deleteProperty(target, key) {
    console.log("deleteProperty", target, key);
    return Reflect.deleteProperty(target, key);
  },
});
// 后期实现 effect 后， 对属性的增加 和删除 应该要重新执行for in 对现有值设置的话，不需要重新执行for in
for (let key in p4) {
  console.log(key);
}
console.log("================");
console.log("name" in p4);
console.log("================");
console.log(delete p4.name);
console.log(p4.name);
console.log("================");
console.log(obj.name);
